﻿using System;

#pragma warning disable CS8604 // 引用类型参数可能为 null。

namespace Hsenl.Network {
    [MessageHandler]
    public abstract class AMessageHandler<T> : INotifMessageHandler where T : INotifMessage {
        public Type MessageType => typeof(T);

        void INotifMessageHandler.Handle(Span<byte> message, Network network, long channelId) {
            var t = NetworkSerializer.DeserializeOfMemoryPack<T>(message);
            this.Run(t, network, channelId).Tail();
        }

        private async hvoid Run(T t, Network network, long channelId) {
            await HTask.SwitchToMainThread();
            this.Handle(t, network, channelId);
        }

        protected abstract void Handle(T message, Network network, long channelId);
    }

    // 多线程版本, 消息不等待主线程的更新, 会更快一点, 但需要注意线程安全
    [MessageHandler]
    public abstract class AMessageHandlerMultithreading<T> : INotifMessageHandler where T : INotifMessage {
        public Type MessageType => typeof(T);

        private readonly HThreadTask _threadTask = new();

        void INotifMessageHandler.Handle(Span<byte> message, Network network, long channelId) {
            var t = NetworkSerializer.DeserializeOfMemoryPack<T>(message);
            this.Run(t, network, channelId).Tail();
        }

        private async hvoid Run(T t, Network network, long channelId) {
            await this._threadTask.SwitchToThread();
            this.Handle(t, network, channelId);
        }

        protected abstract void Handle(T message, Network network, long channelId);
    }

    [MessageHandler]
    public abstract class AMessageHandler<TRequest, TResponse> : IRpcMessageHandler where TRequest : IRpcMessage where TResponse : IRpcMessage {
        public Type RequestType => typeof(TRequest);
        public Type ResponseType => typeof(TResponse);

        void IRpcMessageHandler.Handle(Span<byte> message, Network network, long channelId, uint rpcId) {
            var request = NetworkSerializer.DeserializeOfMemoryPack<TRequest>(message);
            this.Run(request, network, channelId, rpcId).Tail();
        }

        private async hvoid Run(TRequest request, Network network, long channelId, uint rpcId) {
            await HTask.SwitchToMainThread();
            this.Handle(request, network, channelId, rpcId);
        }

        protected abstract void Handle(TRequest message, Network network, long channelId, uint rpcId);

        protected void Reply(TResponse response, Network network, long channelId, uint rpcId) {
            network.SendWithRpcId(response, rpcId, channelId);
        }

        protected void Reply(ref TResponse response, Network network, long channelId, uint rpcId) {
            network.SendWithRpcId(ref response, rpcId, channelId);
        }
    }

    [MessageHandler]
    public abstract class AMessageHandlerMultithreading<TRequest, TResponse> : IRpcMessageHandler where TRequest : IRpcMessage where TResponse : IRpcMessage {
        public Type RequestType => typeof(TRequest);
        public Type ResponseType => typeof(TResponse);

        private readonly HThreadTask _threadTask = new();

        void IRpcMessageHandler.Handle(Span<byte> message, Network network, long channelId, uint rpcId) {
            var request = NetworkSerializer.DeserializeOfMemoryPack<TRequest>(message);
            this.Run(request, network, channelId, rpcId).Tail();
        }

        private async hvoid Run(TRequest request, Network network, long channelId, uint rpcId) {
            await this._threadTask.SwitchToThread();
            this.Handle(request, network, channelId, rpcId);
        }

        protected abstract void Handle(TRequest message, Network network, long channelId, uint rpcId);

        protected void Reply(TResponse response, Network network, long channelId, uint rpcId) {
            network.SendWithRpcId(response, rpcId, channelId);
        }

        protected void Reply(ref TResponse response, Network network, long channelId, uint rpcId) {
            network.SendWithRpcId(ref response, rpcId, channelId);
        }
    }
}